using UnityEngine;

// 引入 Mathf 的静态方法，这样我们可以直接调用例如 Sin、Cos、Sqrt 等函数，而不需要每次写 Mathf.Sin()
using static UnityEngine.Mathf;

// FunctionLibrary 是一个静态类，意味着它不能被实例化，只能通过类名直接访问其静态成员
public static class FunctionLibrary
{

	// =========================
	// 委托定义：Function
	// =========================

	// 定义了一个委托类型 Function，它表示一个接收 (float u, float v, float t) 三个参数，
	// 并返回一个三维向量 Vector3 的函数。
	// 这种委托用于统一不同数学函数的签名，方便通过数组或字典管理和调用它们。
	public delegate Vector3 Function(float u, float v, float t);

	// =========================
	// 枚举：FunctionName
	// =========================

	// 定义了一个枚举，列出当前支持的函数类型，每个枚举值对应一个具体的数学函数。
	// 这些函数在下方都有具体实现。
	public enum FunctionName
	{
		Wave,      // 基础波浪
		MultiWave, // 多重波浪叠加
		Ripple,    // 涟漪效果
		Sphere,    // 球体（参数化）
		Torus      // 环面（甜甜圈形状，参数化）
	}

	// =========================
	// 函数数组：functions
	// =========================

	// 这是一个静态的 Function 委托类型的数组，
	// 每个元素是对应于 FunctionName 枚举中某一项的函数实现。
	// 数组的顺序与枚举的顺序一致，比如：
	// functions[0] = Wave
	// functions[1] = MultiWave
	// ...
	static Function[] functions = {
		Wave,
		MultiWave,
		Ripple,
		Sphere,
		Torus
	};

	// =========================
	// 方法：GetFunction
	// =========================

	// 根据传入的 FunctionName 枚举值，返回对应的数学函数（委托）。
	// 比如传入 FunctionName.Wave，就返回 Wave 函数。
	// 这是一种简洁的“函数查找表”或“命令模式”的实现方式。
	public static Function GetFunction(FunctionName name)
	{
		// 将枚举转换为整数索引，然后从 functions 数组中取出对应的函数
		return functions[(int)name];
	}

	// =========================
	// 下面是每个具体的数学函数实现
	// 每个函数都接收 u, v, t 三个参数，返回一个 Vector3，代表一个点的 3D 坐标
	// =========================

	// ---- 1. Wave：基础正弦波浪 ----
	public static Vector3 Wave(float u, float v, float t)
	{
		Vector3 p;
		p.x = u; // x 坐标直接等于 u
				 // y 坐标是一个正弦函数，参数包含 u, v 和时间 t，产生波浪起伏效果
		p.y = Sin(PI * (u + v + t));
		p.z = v; // z 坐标直接等于 v
		return p;
	}

	// ---- 2. MultiWave：多重波浪叠加 ----
	public static Vector3 MultiWave(float u, float v, float t)
	{
		Vector3 p;
		p.x = u; // x 坐标 = u

		// y 坐标由多个正弦函数叠加而成，形成更复杂的波形
		p.y = Sin(PI * (u + 0.5f * t));                    // 第一层波浪
		p.y += 0.5f * Sin(2f * PI * (v + t));              // 第二层，频率更高
		p.y += Sin(PI * (u + v + 0.25f * t));              // 第三层，组合 u 和 v
		p.y *= 1f / 2.5f;                                  // 将所有波叠加后缩小幅度，避免过强

		p.z = v; // z 坐标 = v
		return p;
	}

	// ---- 3. Ripple：涟漪效果 ----
	public static Vector3 Ripple(float u, float v, float t)
	{
		// d 是当前点 (u, v) 到中心点 (0, 0) 的距离
		float d = Sqrt(u * u + v * v);

		Vector3 p;
		p.x = u; // x 坐标 = u

		// y 坐标是一个正弦波，其频率与距离 d 和时间 t 相关，形成从中心扩散的涟漪效果
		// 除以 (1 + 10 * d) 是为了使振幅随着距离增加而衰减，更真实
		p.y = Sin(PI * (4f * d - t));
		p.y /= 1f + 10f * d;

		p.z = v; // z 坐标 = v
		return p;
	}

	// ---- 4. Sphere：参数化球体 ----
	public static Vector3 Sphere(float u, float v, float t)
	{
		// r 是球的半径，会随时间轻微波动，让球看起来有“呼吸”效果
		float r = 0.9f + 0.1f * Sin(PI * (6f * u + 4f * v + t));

		// s 是球面上某一点的“半径”在 XZ 平面上的投影
		float s = r * Cos(0.5f * PI * v);

		Vector3 p;
		// 使用球坐标参数化公式，生成球面上的点
		p.x = s * Sin(PI * u);       // X 坐标
		p.y = r * Sin(0.5f * PI * v); // Y 坐标（上下，球的主轴）
		p.z = s * Cos(PI * u);       // Z 坐标
		return p;
	}

	// ---- 5. Torus：环面（甜甜圈形状）----
	public static Vector3 Torus(float u, float v, float t)
	{
		// r1 是环的主要半径（从环的中心到管子的中心）
		float r1 = 0.7f + 0.1f * Sin(PI * (6f * u + 0.5f * t));

		// r2 是管子的半径（环的“厚度”），也会轻微波动
		float r2 = 0.15f + 0.05f * Sin(PI * (8f * u + 4f * v + 2f * t));

		// s 是环面上点到环中心的距离，随 v 角度变化
		float s = r1 + r2 * Cos(PI * v);

		Vector3 p;
		// 使用环面的参数化公式生成点
		p.x = s * Sin(PI * u);       // X 坐标
		p.y = r2 * Sin(PI * v);      // Y 坐标（管子的高度方向）
		p.z = s * Cos(PI * u);       // Z 坐标
		return p;
	}
}